/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */

package org.apache.directory.studio.persistence.view.wizards;


import java.util.HashSet;
import java.util.Set;

import org.apache.directory.studio.persistence.core.CodeGeneratorContext;
import org.apache.directory.studio.persistence.core.EntryProperties;
import org.apache.directory.studio.persistence.core.JavaUtils;

import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;


/**
 * TODO AddMembersWizard.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class AddMembersWizardPage extends WizardPage
{

    private CheckboxTableViewer checkboxTableViewer;
    private CodeGeneratorContext codeGeneratorContext;
    private TableColumnSorter tableColumnSorter;


    /**
     * Creates a new instance of AddMembersWizardPage.
     *
     * @param pageName
     */
    protected AddMembersWizardPage()
    {
        super( "AddMembersWizardPage" );
        setTitle( "Attributes" );
        setDescription( "Select LDAP attributes and Java members" );
        // setImageDescriptor( //Image to be added );
        setPageComplete( false );
    }


    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl( Composite parent )
    {
        Composite composite = new Composite( parent, SWT.NULL );
        GridLayout layout = new GridLayout( 1, false );
        composite.setLayout( layout );

        createViewer( composite );
        checkboxTableViewer.setContentProvider( new EntryContentProvider() );
        checkboxTableViewer.setLabelProvider( new EntryLabelProvider() );
        checkboxTableViewer.setInput( codeGeneratorContext.getEntryProperties() );
        // Set the sorter for the table
        tableColumnSorter = new TableColumnSorter();
        checkboxTableViewer.setSorter( tableColumnSorter );
        setControl( composite );
    }


    public void setFocus()
    {
        checkboxTableViewer.getControl().setFocus();
    }


    private void createViewer( Composite parent )
    {
        Table table = new Table( parent, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION );
        table.setHeaderVisible( true );
        table.setLinesVisible( true );
        TableLayout tableLayout = new TableLayout();
        tableLayout.addColumnData( new ColumnWeightData( 90 ) );
        tableLayout.addColumnData( new ColumnWeightData( 120 ) );
        tableLayout.addColumnData( new ColumnWeightData( 90 ) );
        tableLayout.addColumnData( new ColumnWeightData( 120 ) );
        table.setLayout( tableLayout );
        GridData pViewerData = new GridData( GridData.FILL_BOTH );
        table.setLayoutData( pViewerData );
        checkboxTableViewer = new CheckboxTableViewer( table );
        final TableViewerColumn col0viewer = new TableViewerColumn( checkboxTableViewer, 0 );
        // set default sorting direction to ascending
        checkboxTableViewer.addOpenListener( new IOpenListener()
        {
            public void open( OpenEvent event )
            {
                checkboxTableViewer.getTable().setSortColumn( col0viewer.getColumn() );
                checkboxTableViewer.refresh();
            }
        } );

        col0viewer.getColumn().setText( "LDAP Attribute" );
        col0viewer.getColumn().addSelectionListener( new SelectionAdapter()
        {
            public void widgetSelected( SelectionEvent e )
            {
                tableColumnSorter.setColumn( 0 );
                int dir = checkboxTableViewer.getTable().getSortDirection();
                if ( checkboxTableViewer.getTable().getSortColumn() == col0viewer.getColumn() )
                {
                    dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
                }
                else
                {
                    dir = SWT.DOWN;
                }
                checkboxTableViewer.getTable().setSortDirection( dir );
                checkboxTableViewer.getTable().setSortColumn( col0viewer.getColumn() );
                checkboxTableViewer.refresh();
            }
        } );
        final TableViewerColumn col1viewer = new TableViewerColumn( checkboxTableViewer, 1 );
        col1viewer.getColumn().setText( "Java Attribute" );
        col1viewer.setEditingSupport( new AttributeEditingSupport( col1viewer.getViewer(), 1, this ) );
        col1viewer.getColumn().addSelectionListener( new SelectionAdapter()
        {
            public void widgetSelected( SelectionEvent e )
            {
                tableColumnSorter.setColumn( 1 );
                int dir = checkboxTableViewer.getTable().getSortDirection();
                if ( checkboxTableViewer.getTable().getSortColumn() == col1viewer.getColumn() )
                {
                    dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
                }
                else
                {
                    dir = SWT.DOWN;
                }
                checkboxTableViewer.getTable().setSortDirection( dir );
                checkboxTableViewer.getTable().setSortColumn( col1viewer.getColumn() );
                checkboxTableViewer.refresh();
            }
        } );
        TableViewerColumn col2viewer = new TableViewerColumn( checkboxTableViewer, 2 );
        col2viewer.getColumn().setText( "Java Type" );
        col2viewer.setEditingSupport( new AttributeEditingSupport( col2viewer.getViewer(), 2, this ) );
        TableViewerColumn col3viewer = new TableViewerColumn( checkboxTableViewer, 3 );
        col3viewer.getColumn().setText( "Cardinality" );
        col3viewer.setEditingSupport( new AttributeEditingSupport( col3viewer.getViewer(), 3, this ) );
        //get checked elements of the viewer
        checkboxTableViewer.addCheckStateListener( new ICheckStateListener()
        {
            public void checkStateChanged( CheckStateChangedEvent event )
            {
                EntryProperties properties = ( EntryProperties ) event.getElement();
                properties.setGen( event.getChecked() );

                dialogChanged();
            }
        } );

        checkboxTableViewer.setCheckStateProvider( new ICheckStateProvider()
        {
            public boolean isGrayed( Object element )
            {
                return false;
            }


            public boolean isChecked( Object element )
            {
                dialogChanged();
                EntryProperties properties = ( EntryProperties ) element;
                return properties.isGen();
            }
        } );
        dialogChanged();
    }


    public void showErrorMessage( String message )
    {
        setMessage( null, DialogPage.NONE );
        setErrorMessage( message );
        setPageComplete( message == null );
    }


    public void setEntryInformation( CodeGeneratorContext entryInformation )
    {
        this.codeGeneratorContext = entryInformation;
    }


    public void dialogChanged()
    {
        // at least one element must be checked
        if ( checkboxTableViewer.getCheckedElements().length == 0 )
        {
            showErrorMessage( "No elements selected" );
            return;
        }
        // check for valid java identifiers
        for ( EntryProperties properties : codeGeneratorContext.getEntryProperties() )
        {
            if ( properties.isGen() && !JavaUtils.isValid( properties.getJavaMemberName() ) )
            {
                showErrorMessage( properties.getJavaMemberName() + " is not a valid Java identifier." );
                return;
            }
        }

        // check for colliding java member names
        Set<String> javaMemberNames = new HashSet<String>();
        for ( EntryProperties properties : codeGeneratorContext.getEntryProperties() )
        {
            if ( properties.isGen() )
            {
                if ( javaMemberNames.contains( properties.getJavaMemberName() ) )
                {
                    showErrorMessage( properties.getJavaMemberName() + " is used more than once." );
                    return;
                }
                javaMemberNames.add( properties.getJavaMemberName() );

            }
        }

        showErrorMessage( null );
    }

}
